#pragma once

#include "Algorithm.hh"
#include "Allocator.hh"
#include "Iterator.hh"
#include "Uninitialized.hh"

namespace snow
{

template <class T, class Alloc = Allocator<T>>
class Vector
{
    using dataAllocator = Alloc;

public:
    using value_type = T;
    using pointer = value_type *;
    using iterator = value_type *;
    using const_iterator = const value_type *;
    using reference = value_type &;
    using const_reference = const value_type &;
    using size_type = size_t;
    using difference_type = ptrdiff_t;

public:
    // constructor, copy, destrutor
    Vector()
        : _start(0), _finish(0), _endOfStorage(0) {}
    explicit Vector(const size_type count);
    Vector(const size_type count, const value_type &value);
    template <class InputIterator>
    Vector(InputIterator first, InputIterator last);
    Vector(const Vector &rhs);
    Vector(Vector &&rhs);
    Vector &operator=(const Vector &rhs);
    Vector &operator=(Vector &&rhs);
    ~Vector();

    // iterator related
    iterator begin() { return _start; }
    iterator end() { return _finish; }
    const_iterator begin() const { return _start; }
    const_iterator end() const { return _finish; }
    const_iterator cbegin() const { return _start; }
    const_iterator cend() const { return _finish; }

    // size capacity related
    size_type size() const { return size_type(end() - begin()); }
    size_type max_size() const { return size_type(-1) / sizeof(value_type); }
    size_type capacity() const { return size_type(_endOfStorage - begin()); }
    bool empty() const { return begin() == end(); }
    void resize(size_type count, value_type val = value_type()); // value_type() 调默认构造 初始值
    void reserve(size_type newCap);                              // 开空间
    void shrink_to_fit();                                        // 回收尚未利用的空间

    // visit elem related
    reference at(size_type pos); // 有越界检查
    reference operator[](size_type pos) { return *(begin() + pos); }
    const_reference operator[](size_type pos) { return *(cbegin() + pos); }
    reference front() { return *(begin()); }
    reference back() { return *(end() - 1); }
    pointer data() { return _start; }

    // modify container related
    // emplace 相关 待补
    void clear();
    void swap(Vector &other); // 与另一个容器交换内容，实质是交换三指针
    void push_back(const value_type &value);
    void pop_back();
    iterator erase(iterator position);
    iterator erase(iterator first, iterator last);
    iterator insert(iterator position, const value_type &value);
    iterator insert(iterator position, size_type count, const value_type &value);
    template <class InputIterator>
    iterator insert(iterator position, InputIterator first, InputIterator *last);

    // 空间配置器
    Alloc get_allocator() { return dataAllocator; }

private:
    // auxiliary function 相关
    iterator allocate(size_type count) { return dataAllocator::allocate(count); }
    void deallocate(iterator position, size_type count) { dataAllocator::deallocate(position, count); }

    void fill_initialize(size_type count, const value_type &value); // 填充并初始化
    void destory_and_deallocate();                                  // 析构并回收空间
    void insert_aux(iterator position, const value_type &value);
    iterator allocate_and_fill(size_type count, const value_type &value);
    template <class InputIterator>
    void allocate_and_copy(InputIterator first, InputIterator last);
    
    void reallocate_and_fill(iterator position, size_type count, const value_type &value);
    template <class InputIterator>
    void reallocate_and_copy(iterator position, InputIterator first, InputIterator last);

private:
    iterator _start;
    iterator _finish;
    iterator _endOfStorage;
};

} // namespace snow